/*
 * Copyright (c) 2024 Black Sesame Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <unistd.h>
#include <iostream>
#include <iomanip>
#include <thread>
#include <chrono>
#include "dal/domain_participant.h"
#include "dal/participant_monitor.h"
#include "dal_cyclonedds/rtps/GuidUtils.hpp"
#include "dal_cyclonedds/entity_impl/DalDomainParticipantImpl.hpp"

static void monitor_callback(dal_participant_monitor_info_t* monitor_info, void* data)
{
    (void*)data;
    int i;
    std::string participant_name;
    if (monitor_info->participant_name.length > 0) {
        participant_name =
            std::string(monitor_info->participant_name.str, monitor_info->participant_name.length);
    }

    switch (monitor_info->status) {
        case DAL_PARTICIPANT_ONLINE:
            std::cout << "[DAL_PARTICIPANT_ONLINE] guid:";
            break;
        case DAL_PARTICIPANT_OFFLINE_NORMALLY:
            std::cout << "[DAL_PARTICIPANT_OFFLINE_NORMALLY] guid:";
            break;
        case DAL_PARTICIPANT_OFFLINE_ABNORMALLY:
            std::cout << "[DAL_PARTICIPANT_OFFLINE_ABNORMALLY] guid:";
            break;
        default:
            break;
    }
    for (i = 0; i < GUIDPREFIX_SIZE; i++) {
        std::cout << std::hex << std::setfill('0') << std::setw(2)
                  << (int)(monitor_info->guid.guidprefix.value[i]);
    }
    for (i = 0; i < ENTITYID_SIZE; i++) {
        std::cout << std::hex << std::setfill('0') << std::setw(2)
                  << (int)(monitor_info->guid.entity_id.value[i]);
    }
    std::cout << ", participant_name: " << participant_name << std::endl;
}

int main(int argc, char* argv[])
{
    std::cout << "===================================================================" << std::endl;
    std::cout << "[CMD] dal_cyclonedds_monitor <domainID>  # default <domainID> is 0." << std::endl;
    std::cout << "===================================================================" << std::endl;

    uint32_t domainid = 0;
    if (argc == 2) {
        domainid = std::atoi(argv[1]);
    }

    dal_ret_t ret;
    dal_domain_participant_listener_callbacks_t participant_callbacks = { };

    dal_domain_participant_listener_t* participant_listener =
        dal_create_domain_participant_listener(participant_callbacks);

    // 这一步中应当使用ParticipantListenerImpl提供的接口将monitor_callback传递给ParticipantMonitor单例的callback
    // list。
    dal_domain_participant_listener_set_participant_monitor_callback(
        participant_listener, monitor_callback, nullptr);

    dal_domain_participant_qos_t* qos = dal_create_default_participant_qos();
    std::string part_name = "AAAAA_" + std::to_string(getpid());
    qos->participant_name = part_name.c_str();

    std::cout << "Monitor is watching domain : " << domainid
              << ", current participant name : " << part_name << std::endl;

    // 这一步最后应当把domainID传递给ParticipantMonitor单例并判断是否有对应的thread，没有则创建thread并更新引用计数器。
    dal_domain_participant_t* participant =
        dal_create_domain_participant(domainid, qos, participant_listener, DAL_ANY_STATUS);

    std::this_thread::sleep_for(std::chrono::seconds(100));

    dal_delete_domain_participant(participant);

    dal_delete_domain_participant_listener(participant_listener);
}
